using System;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure.Interception;
using System.Linq;
using System.Reflection;
using Comteck.Dependency;
using Comteck.Ktt.Services;
using Comteck.Ktt.Services.Infrastructure;
using Comteck.Ktt.Services.Users;
using Microsoft.Extensions.DependencyInjection;

namespace Comteck.Winforms {
  /// <summary>
  /// Winform容器启动加载项
  /// </summary>
  public class WinformBootstrapper {
    /// <summary>
    /// 创建一个容器
    /// </summary>
    /// <returns></returns>
    public static IServiceProvider ConfigureServices(Action<ServiceCollection> action) {
      var services = new ServiceCollection();

      // 注册DbContext
      services.AddScoped(provider => {
        //var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"test.db3");

        //var connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
        //var connection = new SQLiteConnection(connectionString);
        //var context = new AppDbContext(connection);
        var context = new AppDbContext();
        return context;
      });

      // 延迟
      services.AddScoped(typeof(Lazy<>), typeof(ServiceProviderLazier<>));

      // 注册UnitOfWork
      services.AddScoped<IKttUnitOfWork, KttUnitOfWork>();

      // 注册service
      AddInjectionServices(services, typeof(UserService).Assembly);

      // 注入日志
      DbInterception.Add(new EFLoggerForDebug());

      // 注册服务
      //services.AddScoped<IUserService, UserService>();

      action?.Invoke(services);

      return services.BuildServiceProvider();
    }

    /// <summary>
    /// 自动注入接口, 注入到服务容器IServiceCollection
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public static IServiceCollection AddInjectionServices(IServiceCollection services, Assembly assembly) {
      //服务生命周期映射
      var map = new Dictionary<Type, ServiceLifetime>
      {
             { typeof(ITransientDependency),ServiceLifetime.Transient },
             { typeof(IScopedDependency),ServiceLifetime.Scoped },
             { typeof(ISingletonDependency),ServiceLifetime.Singleton },
         };

      //获取程序集所有实体模型Type
      var typeList = assembly.GetTypes();

      foreach (var type in typeList) {
        map.ToList().ForEach(aMap => {
          //依赖注入接口
          var interfaceDependency = aMap.Key;
          if (interfaceDependency.IsAssignableFrom(type) && interfaceDependency != type && !type.IsAbstract && type.IsClass) {
            //注入实现
            Console.WriteLine("注入实现：" + type.FullName + ", " + aMap.Value.ToString());
            services.Add(new ServiceDescriptor(type, type, aMap.Value));

            //获取当前类的所有接口
            var interfaces = typeList.Where(x => x.IsInterface && x.IsAssignableFrom(type) && x != interfaceDependency).ToList();

            //有接口，注入接口
            if (interfaces.Count > 0) {
              interfaces.ForEach(@inteface => {
                Console.WriteLine("注入接口：" + type.FullName + "," + @inteface.FullName + ", " + aMap.Value.ToString());
                services.Add(new ServiceDescriptor(@inteface, type, aMap.Value));
              });
            }
          }
        });
      };

      return services;
    }
  }
}
